package validators

import (
	"fmt"
	"strings"

	"order-validation-api/models"
)

// ClientValidator 客户端验证器接口
type ClientValidator interface {
	ValidateOrder(order *models.Order) *models.ValidationResult
	GetClientType() models.ClientType
}

// ClientAValidator Client A 验证器
type ClientAValidator struct{}

// NewClientAValidator 创建Client A验证器
func NewClientAValidator() *ClientAValidator {
	return &ClientAValidator{}
}

// GetClientType 获取客户端类型
func (v *ClientAValidator) GetClientType() models.ClientType {
	return models.ClientA
}

// ValidateOrder 验证Client A的订单
func (v *ClientAValidator) ValidateOrder(order *models.Order) *models.ValidationResult {
	result := &models.ValidationResult{IsValid: true}

	// Client A规则：
	// - Type: Market
	// - Currency: HKD
	// - Destination: DestinationA
	// - Minimum Child Notional Amount: HKD 100

	// 验证订单类型
	if order.Type != models.OrderTypeMarket {
		result.AddError("Client A only accepts Market orders")
	}

	// 验证货币
	if strings.ToUpper(order.Currency) != "HKD" {
		result.AddError("Client A only accepts HKD currency")
	}

	// 验证目标
	if order.Destination != "DestinationA" {
		result.AddError("Client A orders must use DestinationA")
	}

	// 验证子订单最小金额
	if order.IsBasketOrder() {
		for i, child := range order.ChildOrders {
			if child.NotionalAmount < 100 {
				result.AddError(fmt.Sprintf("Child order %d: Minimum notional amount for Client A is HKD 100, got %.2f", i+1, child.NotionalAmount))
			}
		}
	}

	return result
}

// ClientBValidator Client B 验证器
type ClientBValidator struct{}

// NewClientBValidator 创建Client B验证器
func NewClientBValidator() *ClientBValidator {
	return &ClientBValidator{}
}

// GetClientType 获取客户端类型
func (v *ClientBValidator) GetClientType() models.ClientType {
	return models.ClientB
}

// ValidateOrder 验证Client B的订单
func (v *ClientBValidator) ValidateOrder(order *models.Order) *models.ValidationResult {
	result := &models.ValidationResult{IsValid: true}

	// Client B规则：
	// - Type: Limit
	// - Currency: USD
	// - Destination: DestinationB
	// - Minimum Basket Notional Amount: USD 10000
	// - Minimum Child Notional Amount: USD 1000

	// 验证订单类型
	if order.Type != models.OrderTypeLimit {
		result.AddError("Client B only accepts Limit orders")
	}

	// 验证货币
	if strings.ToUpper(order.Currency) != "USD" {
		result.AddError("Client B only accepts USD currency")
	}

	// 验证目标
	if order.Destination != "DestinationB" {
		result.AddError("Client B orders must use DestinationB")
	}

	// 验证篮子订单最小金额
	if order.IsBasketOrder() {
		if order.NotionalAmount < 10000 {
			result.AddError(fmt.Sprintf("Minimum basket notional amount for Client B is USD 10000, got %.2f", order.NotionalAmount))
		}

		// 验证子订单最小金额
		for i, child := range order.ChildOrders {
			if child.NotionalAmount < 1000 {
				result.AddError(fmt.Sprintf("Child order %d: Minimum notional amount for Client B is USD 1000, got %.2f", i+1, child.NotionalAmount))
			}
		}
	}

	return result
}

// ClientCValidator Client C 验证器
type ClientCValidator struct{}

// NewClientCValidator 创建Client C验证器
func NewClientCValidator() *ClientCValidator {
	return &ClientCValidator{}
}

// GetClientType 获取客户端类型
func (v *ClientCValidator) GetClientType() models.ClientType {
	return models.ClientC
}

// ValidateOrder 验证Client C的订单
func (v *ClientCValidator) ValidateOrder(order *models.Order) *models.ValidationResult {
	result := &models.ValidationResult{IsValid: true}

	// Client C规则：
	// - Type: Limit or Market
	// - Currency: USD
	// - Destination: Market -> DestinationA, Limit -> DestinationB
	// - No minimum amount
	// - Maximum Parent Notional Amount: USD 100000

	// 验证订单类型（Limit或Market都可以）
	if order.Type != models.OrderTypeLimit && order.Type != models.OrderTypeMarket {
		result.AddError("Client C only accepts Limit or Market orders")
	}

	// 验证货币
	if strings.ToUpper(order.Currency) != "USD" {
		result.AddError("Client C only accepts USD currency")
	}

	// 验证目标根据订单类型
	expectedDestination := ""
	switch order.Type {
	case models.OrderTypeMarket:
		expectedDestination = "DestinationA"
	case models.OrderTypeLimit:
		expectedDestination = "DestinationB"
	}

	if order.Destination != expectedDestination {
		result.AddError(fmt.Sprintf("Client C %s orders must use %s, got %s", order.Type, expectedDestination, order.Destination))
	}

	// 验证最大父订单金额
	if order.NotionalAmount > 100000 {
		result.AddError(fmt.Sprintf("Maximum parent notional amount for Client C is USD 100000, got %.2f", order.NotionalAmount))
	}

	return result
}

// ClientValidatorFactory 客户端验证器工厂
type ClientValidatorFactory struct {
	validators map[models.ClientType]ClientValidator
}

// NewClientValidatorFactory 创建客户端验证器工厂
func NewClientValidatorFactory() *ClientValidatorFactory {
	factory := &ClientValidatorFactory{
		validators: make(map[models.ClientType]ClientValidator),
	}

	// 注册所有客户端验证器
	factory.RegisterValidator(NewClientAValidator())
	factory.RegisterValidator(NewClientBValidator())
	factory.RegisterValidator(NewClientCValidator())

	return factory
}

// RegisterValidator 注册验证器
func (f *ClientValidatorFactory) RegisterValidator(validator ClientValidator) {
	f.validators[validator.GetClientType()] = validator
}

// GetValidator 获取验证器
func (f *ClientValidatorFactory) GetValidator(clientType models.ClientType) (ClientValidator, error) {
	validator, exists := f.validators[clientType]
	if !exists {
		return nil, fmt.Errorf("no validator found for client type: %s", clientType)
	}
	return validator, nil
}

// GetSupportedClients 获取支持的客户端类型
func (f *ClientValidatorFactory) GetSupportedClients() []models.ClientType {
	clients := make([]models.ClientType, 0, len(f.validators))
	for clientType := range f.validators {
		clients = append(clients, clientType)
	}
	return clients
}